#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <stdio.h>


/*************************** Init interface **************************/

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->labelGenreNoun->show();
    ui->radioMaleNoun->show();
    ui->radioFemaleNoun->show();

    ui->labelPlural->show();
    ui->lineEditPlural->show();

    ui->labelFemale->hide();
    ui->lineEditFemale->hide();

    ui->labelGroup->hide();
    ui->radioButtonG1->hide();
    ui->radioButtonG2->hide();
    ui->radioButtonG3->hide();

    ui->labelTrans->hide();
    ui->radioButtonINTR->hide();
    ui->radioButtonTRANS->hide();

    ui->radioNoun->click();
    ui->radioMaleNoun->click();
    ui->radioButtonG1->click();
    ui->radioButtonINTR->click();
    statusLoadMesg.append("Loaded: not yet");
    setStatusMesg();
    inforDialog = new InformationDialog();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::on_radioNoun_clicked(bool checked)
{
    if (checked) {        
        ui->labelGenreNoun->show();
        ui->radioMaleNoun->show();
        ui->radioFemaleNoun->show();

        ui->labelPlural->show();
        ui->lineEditPlural->show();

        ui->labelFemale->hide();
        ui->lineEditFemale->hide();

        ui->labelGroup->hide();
        ui->radioButtonG1->hide();
        ui->radioButtonG2->hide();
        ui->radioButtonG3->hide();

        ui->labelTrans->hide();
        ui->radioButtonINTR->hide();
        ui->radioButtonTRANS->hide();
    }
}

void MainWindow::on_radioVerb_clicked(bool checked)
{
    if (checked) {
        ui->labelGenreNoun->hide();
        ui->radioMaleNoun->hide();
        ui->radioFemaleNoun->hide();

        ui->labelPlural->hide();
        ui->lineEditPlural->hide();

        ui->labelFemale->hide();
        ui->lineEditFemale->hide();

        ui->labelGroup->show();
        ui->radioButtonG1->show();
        ui->radioButtonG2->show();
        ui->radioButtonG3->show();

        ui->labelTrans->show();
        ui->radioButtonINTR->show();
        ui->radioButtonTRANS->show();
    }
}

void MainWindow::on_radioAdjective_clicked(bool checked)
{
    if (checked) {
        ui->labelGenreNoun->hide();
        ui->radioMaleNoun->hide();
        ui->radioFemaleNoun->hide();

        ui->labelPlural->show();
        ui->lineEditPlural->show();

        ui->labelFemale->show();
        ui->lineEditFemale->show();

        ui->labelGroup->hide();
        ui->radioButtonG1->hide();
        ui->radioButtonG2->hide();
        ui->radioButtonG3->hide();

        ui->labelTrans->hide();
        ui->radioButtonINTR->hide();
        ui->radioButtonTRANS->hide();
    }
}


/************************ Init corba ********************************/

//////////////////////////////////////////////////////////////////////
void MainWindow::initArguments(int _argc, char **_argv) {
    initCorba(dictref, _argc, _argv);
    clearAddingValues();
    clearModifyValues();
    clearDeleteValues();   
}

//////////////////////////////////////////////////////////////////////
int MainWindow::initCorba(Dictionnary_var _dictref, int argc, char **argv) {
    try {
        orb = CORBA::ORB_init(argc, argv);
        CORBA::Object_var obj = getObjectReference(orb);
        dictref = Dictionnary::_narrow(obj);
    } catch (CORBA::TRANSIENT&) {
        cerr << "Caught system exception TRANSIENT -- unable to contact the "
                << "server." << endl;
    } catch (CORBA::SystemException& ex) {
        cerr << "Caught a CORBA::" << ex._name() << endl;
    } catch (CORBA::Exception& ex) {
        cerr << "Caught CORBA::Exception: " << ex._name() << endl;
    } catch (omniORB::fatalException& fe) {
        cerr << "Caught omniORB::fatalException:" << endl;
        cerr << " file: " << fe.file() << endl;
        cerr << " line: " << fe.line() << endl;
        cerr << " mesg: " << fe.errmsg() << endl;
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////
// Prendre l'object dictonnary de serveur

CORBA::Object_ptr MainWindow::getObjectReference(CORBA::ORB_ptr orb) {
    CosNaming::NamingContext_var rootContext;
    try {
        // Obtain a reference to the root context of the Name service:        
        CORBA::Object_var obj = orb->resolve_initial_references("NameService");
        // Narrow the reference returned.
        rootContext = CosNaming::NamingContext::_narrow(obj);
        if (CORBA::is_nil(rootContext)) {
            cerr << "Failed to narrow the root naming context." << endl;
            return CORBA::Object::_nil();
        }
    } catch (CORBA::NO_RESOURCES&) {
        cerr << "Caught NO_RESOURCES exception. You must configure omniORB "
                << "with the location" << endl
                << "of the naming service." << endl;
        return 0;
    } catch (CORBA::ORB::InvalidName& ex) {
        // This should not happen!
        cerr << "Service required is invalid [does not exist]." << endl;
        return CORBA::Object::_nil();
    }
    // Create a name object, containing the name test/context:
    CosNaming::Name name;
    name.length(2);
    name[0].id = (const char*) "Dictionnary"; // string copied
    name[0].kind = (const char*) "dictionnary_context"; // string copied
    name[1].id = (const char*) "Dictionnary";
    name[1].kind = (const char*) "Object";
    // Note on kind: The kind field is used to indicate the type
    // of the object. This is to avoid conventions such as that used
    // by files (name.type -- e.g. test.ps = postscript etc.)
    try {
        // Resolve the name to an object reference.
        return rootContext->resolve(name);
    } catch (CosNaming::NamingContext::NotFound& ex) {
        // This exception is thrown if any of the components of the
        // path [contexts or the object] aren’t found:
        cerr << "Context not found." << endl;
    } catch (CORBA::TRANSIENT& ex) {
        cerr << "Caught system exception TRANSIENT -- unable to contact the "
                << "naming service." << endl
                << "Make sure the naming server is running and that omniORB is "
                << "configured correctly." << endl;
    } catch (CORBA::SystemException& ex) {
        cerr << "Caught a CORBA::" << ex._name()
                << " while using the naming service." << endl;
        return 0;
    }
    return CORBA::Object::_nil();
}

//////////////////////////////////////////////////////////////////////
// Stop
void MainWindow::destroy() {
    orb->destroy();
}




/********************* Les fontions de dictionnaire ******************/

//////////////////////////////////////////////////////////////////////
// trier ascendant
void MainWindow::on_actionSort_Ascending_activated()
{
    try {
        sortAscendingDict(dictref);
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: not yet");
        setStatusMesg();
        inforDialog->show("Sort ascending success!");        
    } catch (...) {
        cerr << "Sort ascending " << endl;
    }
    return;
}

//////////////////////////////////////////////////////////////////////
// trier descendant
void MainWindow::on_actionSort_Descending_activated()
{
    try {
        sortDescendingDict(dictref);
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: not yet");
        setStatusMesg();
        inforDialog->show("Sort descending success!");
    } catch (...) {
        cerr << "Sort descending " << endl;
    }
    return;
}

//////////////////////////////////////////////////////////////////////
// Load
void MainWindow::on_actionLoad_activated()
{
    try {
       loadDict(dictref);       
       statusLoadMesg.clear();
       statusLoadMesg.append("Loaded: yes");
       setStatusMesg();
       inforDialog->show("Load success!");
    } catch (...) {
        cerr << "Load " << endl;
    }
    return;
}

//////////////////////////////////////////////////////////////////////
// Save
void MainWindow::on_actionSave_activated()
{
    try {
        saveDict(dictref);
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: yes");
        setStatusMesg();
        inforDialog->show("Save success!");
    } catch (...) {
        cerr << "Sort descending " << endl;
    }
    return;
}

//////////////////////////////////////////////////////////////////////
// Length
void MainWindow::on_actionDictLength_activated()
{
    try {
        CORBA::ULong length = dictLength(dictref);
        statusLengthMesg.clear();
        statusLengthMesg.append("                  Length: ");
        long  tmp = (long)length;
        char tmp2[10];
        sprintf(tmp2, "%d", tmp);        
        statusLengthMesg.append(tmp2);
        setStatusMesg();
        QString message = QString("Dictionary length: ") + QString(tmp2);
        inforDialog->show(message.toStdString());
    } catch (...) {
        cerr << "Length " << endl;
    }
    return;
}

//////////////////////////////////////////////////////////////////////
// Exit
void MainWindow::on_actionExit_activated()
{
    destroy();
    exit(1);
}

//////////////////////////////////////////////////////////////////////
// Add a new word
void MainWindow::on_buttonAdd_clicked()
{   try {
        const char* term;
        CategoryValue category;
        PropertyType property;
        const char* def;
        //QByteArray ba;

        // get term
        QString _term = ui->lineEditTerm->text();        
        QByteArray ba = _term.toLatin1();
        term = ba.data();

        // get definition
        QString _def = ui->textEditAdd->toPlainText();
        QByteArray ba1 = _def.toLatin1();
        def = ba1.data();
        // get type
        if (ui->radioNoun->isChecked()) {

            category = NOM;
            PropNom prop;

            // get genre - Féminin ou Masculin
            if (ui->radioMaleNoun->isChecked()) {
                prop.genre = MASC;
            } else {
                prop.genre = FEM;
            }

            // get plural
            QString _plural = ui->lineEditPlural->text();
            //ba.clear();
            QByteArray ba3 = _plural.toLatin1();
            const char* plural = ba3.data();
            prop.pluriel = plural;
            property.pNom(prop);            
        } else
        if (ui->radioAdjective->isChecked()) {
            category = ADJ;
            PropAdj prop;
            // get plural
            QString _plural = ui->lineEditPlural->text();
            //ba.clear();
            QByteArray ba4 = _plural.toLatin1();
            const char* plural = ba4.data();
            prop.pluriel = plural;
            property.pAdj(prop);
            // get female
            QString _female = ui->lineEditFemale->text();
            //ba.clear();
            QByteArray ba5 = _female.toLatin1();
            const char* female = ba5.data();
            prop.feminin = female;
            property.pAdj(prop);
        } else
        if (ui->radioVerb->isChecked()) {
            category = VER;
            PropVer prop;
            // get groupe
            if (ui->radioButtonG1->isChecked()) {
                prop.groupe = G1;
            } else if (ui->radioButtonG2->isChecked()) {
                prop.groupe = G2;
            } else {
                prop.groupe = G3;
            }
            // get trans
            if (ui->radioButtonINTR->isChecked()) {
                prop.transitivite = INTR;
            } else {
                prop.transitivite = TRANS;
            }
            property.pVer(prop);
        }
        const QString s = "";
        if (_term.isEmpty()) {
            return;
        }
        addEntity(dictref, term, category, property, def);
        clearAddingValues();
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: not yet");
        setStatusMesg();
        QString message = QString("The word '") + QString(term) + QString("' is added");
        inforDialog->show(message.toStdString());
    } catch (...) {
        cerr << "add " << endl;
    }
    return;
}

void MainWindow::on_buttonDelete_clicked()
{
    try {
        QString _term = ui->lineEditDelete->text();
        QByteArray ba = _term.toLatin1();
        const char* term = ba.data();
        const QString s = "";
        if (_term.isEmpty()) {
            return;
        }
        delEntity(dictref, term);
        clearDeleteValues();
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: not yet");
        setStatusMesg();
        QString message = QString("The word '") + QString(term) + QString("' is deleted");
        inforDialog->show(message.toStdString());
    } catch (...) {
        cerr << "delete " << endl;
    }
    return;
}

void MainWindow::on_buttonModify_clicked()
{
    try  {
        // term
        QString _term = ui->lineEditModify->text();
        QByteArray ba = _term.toLatin1();
        const char* term = ba.data();
        // get definition
        QString _newdef = ui->textEditModify->toPlainText();
        ba = _newdef.toLatin1();
        const char* newdef = ba.data();
        const QString s = "";
        if (_term.isEmpty()) {
            return;
        }
        modifDefinition(dictref, term, newdef);
        clearModifyValues();
        statusSaveMesg.clear();
        statusSaveMesg.append("         Saved: not yet");
        setStatusMesg();
        QString message = QString("The word '") + QString(term) + QString("' is modified");
        inforDialog->show(message.toStdString());
    } catch (...) {
        cerr << "modify " << endl;
    }
    return;
}

void MainWindow::clearAddingValues() {
    ui->lineEditTerm->clear();    
    ui->textEditAdd->clear();\

    ui->radioMaleNoun->click();
    ui->lineEditPlural->clear();
    ui->lineEditFemale->clear(); 

    ui->radioButtonG1->click();
    ui->radioButtonINTR->click();
    ui->lineEditTerm->setFocus();;
}

void MainWindow::clearModifyValues() {
    ui->lineEditModify->clear();
    ui->textEditModify->clear();
    ui->lineEditModify->setFocus();
}

void MainWindow::clearDeleteValues() {
    ui->lineEditDelete->clear();
    ui->lineEditDelete->setFocus();   
}

void MainWindow::setStatusMesg() {
    statusMesg.clear();
    statusMesg.append(statusLoadMesg);
    statusMesg.append(statusSaveMesg);
    statusMesg.append(statusLengthMesg);    
    ui->statusBar->showMessage(statusMesg, 0);
}
